package com.colin.datamove.util;

import org.apache.commons.lang3.StringUtils;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Date;
import java.util.Properties;

/**
 * 邮件发送
 */
public class EmailUtils {
    /**
     * 发件人的 邮箱 和 密码（替换为自己的邮箱和密码）
     * PS: 某些邮箱服务器为了增加邮箱本身密码的安全性，给 SMTP 客户端设置了独立密码（有的邮箱称为“授权码”）,
     * 对于开启了独立密码的邮箱, 这里的邮箱密码必需使用这个独立密码（授权码）。
     */
    private static String emailAccount = "*";
    private static String emailPassword = "*";
    /**
     * 发件人邮箱的 SMTP 服务器地址, 必须准确, 不同邮件服务器地址不同, 一般(只是一般, 绝非绝对)格式为: smtp.xxx.com
     * 网易163邮箱的 SMTP 服务器地址为: smtp.163.com
     */
    private static String mailSMTPHost = "*";
    /**
     * 端口，一般smtp为465
     */
    private static int mailPort = 80;
    /**
     * 收件人邮箱
     */
    private static String receiveMailAccount = "*";
    /**
     * 抄送人邮箱
     */
    private static String copyForMailAccount;

    /**
     * 预警邮件发送标识，保证只发送一次
     * 重启后重置
     */
    private static boolean canSendAlert = true;

    /**
     * 预警邮件发送
     *
     * @param content 异常内容
     */
    public static void sendAlert(String content) {
        try {
            if (canSendAlert) {
                canSendAlert = false;
                send("【预警】datamove异常", content, null);
            }
        } catch (Exception e) {
            LogUtil.error("sendAlert_error", e);
        }

    }

    /**
     * 邮件发送
     *
     * @param title   主题
     * @param content 内容
     * @param file    附件
     */
    public static void send(String title, String content, String file) throws Exception {
        // 1. 创建参数配置, 用于连接邮件服务器的参数配置
        Properties props = new Properties();
//        //使用的协议（JavaMail规范要求）
//        props.setProperty("mail.transport.protocol", "smtp");
//        //发件人的邮箱的 SMTP 服务器地址
//        props.setProperty("mail.smtp.host", mailSMTPHost);
//        //需要请求认证
//        props.setProperty("mail.smtp.auth", "true");
//        //端口，一般smtp为465
//        props.setProperty("mail.smtp.port", mailPort);
//        props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
//        props.setProperty("mail.smtp.socketFactory.fallback", "false");
//        props.setProperty("mail.smtp.socketFactory.port", mailPort);

        // 2. 根据配置创建会话对象, 用于和邮件服务器交互
        Session session = Session.getDefaultInstance(props);
        // 设置为debug模式, 可以查看详细的发送 log
        session.setDebug(false);

        // 3. 创建一封邮件
        MimeMessage message = createMimeMessage(session, title, content, file);

        // 4. 根据 Session 获取邮件传输对象
        Transport transport = session.getTransport("smtp");

        // 5. 使用 邮箱账号 和 密码 连接邮件服务器, 这里认证的邮箱必须与 message 中的发件人邮箱一致, 否则报错
        transport.connect(mailSMTPHost, mailPort, emailAccount, emailPassword);

        // 6. 发送邮件, 发到所有的收件地址, message.getAllRecipients() 获取到的是在创建邮件对象时添加的所有收件人, 抄送人, 密送人
        transport.sendMessage(message, message.getAllRecipients());

        // 7. 关闭连接
        transport.close();
    }

    /**
     * 创建邮件
     *
     * @param session     会话对象
     * @param mailTitle   主题
     * @param mailContext 内容
     * @param file        附件(本地文件路径)
     */
    private static MimeMessage createMimeMessage(Session session, String mailTitle, String mailContext, String file) throws Exception {
        // 1. 创建一封邮件
        MimeMessage message = new MimeMessage(session);

        // 2. From: 发件人
        message.setFrom(new InternetAddress(emailAccount));

        // 3. To: 收件人（可以增加多个收件人、抄送、密送）
        String[] addresss = receiveMailAccount.split(",");
        InternetAddress[] to = new InternetAddress[addresss.length];
        if (addresss.length > 0) {
            for (int i = 0; i < addresss.length; i++) {
                to[i] = new InternetAddress(addresss[i]);
            }
        }
        message.addRecipients(MimeMessage.RecipientType.TO, to);
        //CC:抄送人
        if (StringUtils.isNotBlank(copyForMailAccount)) {
            String[] copyAddresss = copyForMailAccount.split(",");
            InternetAddress[] cc = new InternetAddress[addresss.length];
            if (addresss.length > 0) {
                for (int i = 0; i < copyAddresss.length; i++) {
                    cc[i] = new InternetAddress(copyAddresss[i]);
                }
            }
            message.addRecipients(MimeMessage.RecipientType.CC, cc);
        }

        // 4. Subject: 邮件主题
        message.setSubject(mailTitle, "UTF-8");

        // 向multipart对象中添加邮件的各个部分内容，包括文本内容和附件
        Multipart multipart = new MimeMultipart();

        // 5. Content: 邮件正文（可以使用html标签）
        if (StringUtils.isNotBlank(mailContext)) {
            MimeBodyPart contentPart = new MimeBodyPart();
            contentPart.setContent(mailContext, "text/html;charset=UTF-8");
            multipart.addBodyPart(contentPart);
        }
        // 6. 附件
        if (StringUtils.isNotBlank(file)) {
            MimeBodyPart filePart = new MimeBodyPart();
            File usFile = new File(file);
            DataSource source = new FileDataSource(file);
            filePart.setDataHandler(new DataHandler(source));
            byte[] encode = Base64.getEncoder().encode(usFile.getName().getBytes());
            String name = new String(encode, StandardCharsets.UTF_8);
            filePart.setFileName("=?GBK?B?" + name + "?=");
            multipart.addBodyPart(filePart);
        }

        // 将multipart对象放到message中
        message.setContent(multipart);

        // 7. 设置发件时间
        message.setSentDate(new Date());

        // 8. 保存设置
        message.saveChanges();

        return message;
    }

    public static void main(String[] args) throws Exception {
//        String pa = "C:\\Users\\zhaolz\\Desktop\\11.xlsx";
        send("测试", "这是一封测试邮件", null);
    }
}
